OpenGL,窗体和图形的渲染(包含OpenGL、GLFW、GLAD) 您所在的位置:网站首页 Opengl的VAO个人理解 OpenGL,窗体和图形的渲染(包含OpenGL、GLFW、GLAD)

OpenGL,窗体和图形的渲染(包含OpenGL、GLFW、GLAD)

2023-12-26 13:30| 来源: 网络整理| 查看: 265

运行环境:Linux 、C++ 本教程仅个人学习总结第一个hello world,渲染一个窗体渲染一个矩形

本教程仅个人学习总结

一切参考资源:都在官网。

1、安装glfw

首先下载glfw : 点击这里

1、下载 2、解压 3、mkdir build && cd build 4、cmake … && make -j4 5、cd … 6、将此目录下的include目录里面的东西全拷到自己工程的include中 7、cd build/src 这个目录下面的静态库(默认编译是静态库) libglfw3.a ,为我们需要的库

1、 GLFW是一个专门针对OpenGL的C语言库,它提供了一些渲染物体所需的最低限度的接口。它允许用户创建OpenGL上下文、定义窗口参数以及处理用户输入,对我们来说这就够了。

因为OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发者身上,开发者需要在运行时获取函数地址并将其保存在一个函数指针中供以后使用

2、安装GLAD GLAD是一个开源的库,它能解决我们上面提到的那个繁琐的问题。GLAD的配置与大多数的开源库有些许的不同,GLAD使用了一个在线服务。在这里我们能够告诉GLAD需要定义的OpenGL版本,并且根据这个版本加载所有相关的OpenGL函数。 打开GLAD的在线服务,将语言(Language)设置为C/C++,在API选项中,选择3.3以上的OpenGL(gl)版本(我们的教程中将使用3.3版本,但更新的版本也能用)。之后将模式(Profile)设置为Core,并且保证选中了生成加载器(Generate a loader)选项。现在可以先(暂时)忽略扩展(Extensions)中的内容。都选择完之后,点击生成(Generate)按钮来生成库文件。

GLAD现在应该提供给你了一个zip压缩文件,包含两个头文件目录,和一个glad.c文件。将两个头文件目录(glad和KHR)复制到你的Include文件夹中(或者增加一个额外的项目指向这些目录),并添加glad.c文件到你的工程中。

3、OpenGL安装。本站一大堆教程这里就不多说了。

第一个hello world,渲染一个窗体

上文中说到GLFW提供了一系列操作OPENGL的接口,首先第一步即为初始化GLFW环境

#include "glfw3.h"

初始化前我们需要先知道GLFW的版本。

int major = 0, minor = 0, rev = 0; glfwGetVersion(&major, &minor, &rev); //查看GLFW版本号 std::cout std::cout std::cout int major = 0, minor = 0, rev = 0; glfwGetVersion(&major, &minor, &rev); //查看GLFW版本号 std::cout std::cout //如果是的话该函数返回true然后渲染循环便结束了,之后为我们就可以关闭应用程序了。 processInput(window); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(window); //函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上 glfwPollEvents(); //函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。 } //销毁所有窗口 glfwTerminate(); return 0; } void set_render_size(GLFWwindow *window, int width, int height) { std::cout // glfw: initialize and configure // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif // glfw window creation // -------------------- GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } // glfw: whenever the window size changed (by OS or user resize) this callback function executes // --------------------------------------------------------------------------------------------- void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }

接下来我们要开始渲染一个矩形了

首先我们现创建顶点着色器。

// 创建顶点着色器 //glCreateShader 创建着色器 参数是着色器类型:GL_VERTEX_SHADER是顶点着色器 unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);

注意一下上文有这样一句话

有些着色器可以由开发者配置,因为允许用自己写的着色器来代替默认的,所以能够更细致地控制图形渲染管线中的特定部分了。因为它们运行在GPU上,所以节省了宝贵的CPU时间。OpenGL着色器是用OpenGL着色器语言(OpenGL Shading Language, GLSL)写成的

我们创建了顶点着色器,接下来我们就要编写着色器的程序。

const char *vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" "}\0"; // 创建顶点着色器 unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); //替换着色器中的代码:顶点 glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); //编译已存储在由 指定的着色器对象中的源代码字符串 glCompileShader(vertexShader);

接着我们在创建一个片段着色器

const char *fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "void main()\n" "{\n" " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" "}\n\0"; // 创建片段着色器 unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //替换着色器中的代码 : 片段 glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); //编译已存储在由 指定的着色器对象中的源代码字符串 glCompileShader(fragmentShader); // check for shader compile errors glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { //返回着色器对象的信息日志 glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); std::cout 0.5f, 0.5f, 0.0f, // top right 0.5f, -0.5f, 0.0f, // bottom right -0.5f, -0.5f, 0.0f, // bottom left -0.5f, 0.5f, 0.0f // top left }; unsigned int indices[] = { // note that we start from 0! 0, 1, 3, // first Triangle 1, 2, 3 // second Triangle }; unsigned int VBO, VAO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind glBindBuffer(GL_ARRAY_BUFFER, 0); // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound. //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. glBindVertexArray(0);

全部完整源码

#include #include #include void framebuffer_size_callback(GLFWwindow* window, int width, int height); void processInput(GLFWwindow *window); // settings const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; const char *vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" "}\0"; const char *fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "void main()\n" "{\n" " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" "}\n\0"; int main() { // glfw: initialize and configure // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif // glfw window creation // -------------------- GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout //返回着色器对象的信息日志 glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); std::cout glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); std::cout // note that we start from 0! 0, 1, 3, // first Triangle 1, 2, 3 // second Triangle }; unsigned int VBO, VAO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind glBindBuffer(GL_ARRAY_BUFFER, 0); // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound. //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. glBindVertexArray(0); // uncomment this call to draw in wireframe polygons. //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // render loop // ----------- while (!glfwWindowShouldClose(window)) { // input // ----- processInput(window); // render // ------ glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // draw our first triangle glUseProgram(shaderProgram); glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized //glDrawArrays(GL_TRIANGLES, 0, 6); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // glBindVertexArray(0); // no need to unbind it every time // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) // ------------------------------------------------------------------------------- glfwSwapBuffers(window); glfwPollEvents(); } // optional: de-allocate all resources once they've outlived their purpose: // ------------------------------------------------------------------------ glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glDeleteProgram(shaderProgram); // glfw: terminate, clearing all previously allocated GLFW resources. // ------------------------------------------------------------------ glfwTerminate(); return 0; } // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly // --------------------------------------------------------------------------------------------------------- void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } // glfw: whenever the window size changed (by OS or user resize) this callback function executes // --------------------------------------------------------------------------------------------- void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); }

运行截图 在这里插入图片描述

感谢阅读。 企鹅:918619587



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有